package com.wgh.demo.ai.controller;

import com.wgh.demo.ai.entity.Stock;
import com.wgh.demo.ai.exception.StockImportException;
import com.wgh.demo.ai.service.StockService;

import reactor.core.publisher.Mono;
import reactor.core.publisher.Flux;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.data.domain.Page;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.core.io.buffer.DataBufferUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Date;

@RestController
@RequestMapping("/api/stocks")
public class StockController {

    private static final Logger logger = LoggerFactory.getLogger(StockController.class);
    private final StockService stockService;

    @Autowired
    public StockController(StockService stockService) {
        this.stockService = stockService;
        logger.info("StockController初始化完成");
    }

    // 获取所有股票（响应式，无分页限制）
    @GetMapping
    public Flux<Stock> getAllStocks() {
        return stockService.findAllReactiveWithoutPagination();
    }

    // 获取单个股票（响应式）
    @GetMapping("/{id}")
    public Mono<ResponseEntity<Stock>> getStockById(@PathVariable Long id) {
        return Mono.fromCallable(() -> stockService.findById(id))
                .map(stock -> stock != null ? ResponseEntity.ok(stock) : ResponseEntity.notFound().build());
    }

    // 创建新股票（响应式）
    @PostMapping
    public Mono<ResponseEntity<Stock>> createStock(@RequestBody Stock stock) {
        return Mono.fromCallable(() -> {
            if (stockService.existsByCode(stock.getCode())) {
                return ResponseEntity.status(HttpStatus.CONFLICT).body(null);
            }
            Stock savedStock = stockService.save(stock);
            return ResponseEntity.status(HttpStatus.CREATED).body(savedStock);
        });
    }

    // 更新股票（响应式）
    @PutMapping("/{id}")
    public Mono<ResponseEntity<Stock>> updateStock(@PathVariable Long id, @RequestBody Stock stock) {
        return Mono.fromCallable(() -> stockService.findById(id))
                .flatMap(existingStock -> {
                    if (existingStock == null) {
                        return Mono.just(ResponseEntity.notFound().build());
                    }
                    existingStock.setName(stock.getName());
                    existingStock.setCode(stock.getCode());
                    Stock updatedStock = stockService.save(existingStock);
                    return Mono.just(ResponseEntity.ok(updatedStock));
                });
    }

    // 删除股票（响应式）
    @DeleteMapping("/{id}")
    public Mono<ResponseEntity<Object>> deleteStock(@PathVariable Long id) {
        return Mono.fromCallable(() -> stockService.findById(id))
                .flatMap(stock -> {
                    if (stock == null) {
                        return Mono.just(ResponseEntity.notFound().build());
                    }
                    stockService.deleteById(id);
                    return Mono.just(ResponseEntity.noContent().build());
                });
    }

    // 导入股票CSV文件
    @PostMapping(value = "/import", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public Mono<ResponseEntity<?>> importStocks(@RequestPart("file") FilePart file) {
        logger.info("收到股票导入请求");
        
        if (file == null) {
            logger.warn("文件参数 'file' 不存在");
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("status", HttpStatus.BAD_REQUEST.value());
            errorResponse.put("error", "Bad Request");
            errorResponse.put("message", "文件参数 'file' 不存在");
            errorResponse.put("timestamp", new Date());
            return Mono.just(ResponseEntity.badRequest().body(errorResponse));
        }

        logger.info("文件名: {}", file.filename());

        // 将FilePart转换为字节数组
        ByteArrayOutputStream os = new ByteArrayOutputStream();

        return file.content()
            .doOnNext(dataBuffer -> {
                try {
                    byte[] bytes = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(bytes);
                    os.write(bytes);
                } catch (IOException e) {
                    throw new RuntimeException("读取文件数据失败", e);
                } finally {
                    DataBufferUtils.release(dataBuffer);
                }
            })
            .then(Mono.fromCallable(() -> {
                os.close(); // 关闭流
                byte[] csvData = os.toByteArray();
                logger.info("文件读取完成，数据长度: {}", csvData.length);
                logger.info("文件内容预览: {}", new String(csvData, 0, Math.min(100, csvData.length)));
                return csvData;
            }))
            .flatMap(csvData -> {
                try {
                    StockService.ImportResult result = stockService.importStocksFromCsv(csvData);
                    logger.info("股票导入完成，成功: {}, 失败: {}", result.getSuccessCount(), result.getFailCount());

                    if (result.getFailCount() > 0) {
                        logger.warn("部分股票导入失败: 成功={}, 失败={}", result.getSuccessCount(), result.getFailCount());
                        return Mono.just(ResponseEntity.status(HttpStatus.PARTIAL_CONTENT).body(result));
                    }

                    return Mono.just(ResponseEntity.status(HttpStatus.CREATED).body(result));
                } catch (StockImportException e) {
                    logger.error("股票导入失败: {}", e.getMessage(), e);
                    Map<String, Object> errorResponse = new HashMap<>();
                    errorResponse.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
                    errorResponse.put("error", "Internal Server Error");
                    errorResponse.put("message", e.getMessage());
                    errorResponse.put("timestamp", new Date());
                    return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse));
                } catch (Exception e) {
                    logger.error("股票导入失败: {}", e.getMessage(), e);
                    Map<String, Object> errorResponse = new HashMap<>();
                    errorResponse.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
                    errorResponse.put("error", "Internal Server Error");
                    errorResponse.put("message", "股票导入过程中发生错误: " + e.getMessage());
                    errorResponse.put("timestamp", new Date());
                    return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse));
                }
            });
    }    // 股票分页查询API
    @GetMapping("/page")
    public Mono<ResponseEntity<Page<Stock>>> getStocksByPage(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        return stockService.findAllReactivePage(page, size)
                .map(ResponseEntity::ok)
                .defaultIfEmpty(ResponseEntity.notFound().build());
    }

    // 股票下拉框分页查询API
    @GetMapping("/dropdown")
    public Flux<Stock> getStocksForDropdown(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size) {
        return stockService.findAllReactive(page, size);
    }
}